package cn.wolfcode.luowowo.interceptor;

import cn.wolfcode.luowowo.util.JsonResult;
import cn.wolfcode.luowowo.util.Md5Utils;
import com.alibaba.fastjson.JSON;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 签名拦截(防篡改)
 */
public class SignInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            //不是动态的请求就直接放行（访问静态页面）
            return true;
        }

        /**
         * Map<String, String[]> map = request.getParameterMap();
         * {
         *     aa:["11"]
         *     bb:["22"]
         *     cc:["33"]
         *     sign:["MD5加密后的sign"]
         * }
         * 参数转成不包含数组的样式，最后得到：
         * {
         *     aa:"11"
         *     bb:"22"
         *     cc:"33"
         * }
         */

        //签名验证
        Map<String, String[]> map = request.getParameterMap(); //把穿过来的4个参数封装成一个map
        Set<String> keys = map.keySet();
        Map<String, Object> param = new HashMap<>();
        for (String s : map.keySet()) { //map遍历
            if ("sign".equalsIgnoreCase(s)) {//跳过sign的键
                continue;
            }
            param.put(s, arrayToString(map.get(s)));//排除数组
        }
        String signatures = Md5Utils.signatures(param); //获取服务端签名 sign_server
        String sign = request.getParameter("sign"); //获取客户端的前面 sign_client
        //比较前端得到的sign和后端生成的sign是否一致
        if (sign == null || !sign.equalsIgnoreCase(signatures)) {
            //不相等，签名失败
            response.setContentType("text/json;charset=UTF-8");
            response.getWriter().write(JSON.toJSONString(new JsonResult(501, "签名校验失败", "不好意思咯")));
            return false;
        }
        return true;
    }


    //排除数组的方法
    private String arrayToString(String[] array) {
        StringBuilder sb = new StringBuilder(10);
        for (String s : array) {
            sb.append(s);
        }
        return sb.toString();
    }
}